<?php

namespace app\admin\controller\fans;

use app\wechat\controller\Openid;
use app\wechat\controller\Platform;
use think\facade\Cache;
use think\facade\Log;

/**
 * @author zero
 * @Time 2018/12/18
 *
 * Class Infoserver
 * @package app\admin\controller\fans
 *
 * 查询公众号所有粉丝详细信息
 * swoole服务端
 */
class Infoserver
{

    public $server = null; //swoole服务
    public $platform = null; // easywechat第三方平台
    public $openid_list = array(); // 所有openid

    public function __construct()
    {
        $this->server = new \swoole_server("127.0.0.1", 9508); // 建立tcp服务端
        $this->platform = new Platform(); // 第三方平台实例

        // 服务配置
        $this->server->set(array(
//            'daemonize' => 1, // 守护进程
            'worker_num' => 10, // worker进程数 CPU核数1-4倍
            'log_file' => '/www/wwwroot/wechat.nanxuncn.cn/runtime/log/repetrate_swoole.log', // 日志文件路径
            'task_worker_num' => 160, // task进程数
        ));

        // 监听方法
        $this->server->on('connect', [$this, 'on_connect']);
        $this->server->on('receive', [$this, 'on_receive']);
        $this->server->on('task', [$this, 'on_task']);
        $this->server->on('close', [$this, 'on_close']);

        // 开始服务
        echo 'start';
        $this->server->start();
    }

    // 监听客户端连接事件
    public function on_connect($serv, $fd)
    {
        echo "客户端连接.\n";
    }

    // 监听接受消息事件
    public function on_receive($serv, $fd, $reactor_id, $data)
    {
        // 拿出消息数据
        $arr = json_decode($data, true);
        $appid = $arr['appid'];
        $refresh_token = $arr['refresh_token'];
        // 拿到所有粉丝openid
        $token = Cache::get('access_token' . $appid);
        if (!$token) {
            $token = $this->platform->get_gh_token_no_db($appid, $refresh_token);
            if (!$token) {
                return;
            }
        }

        $openidInfo = $this->get_all_openid($token);

        if ($openidInfo != '') {
            echo count($openidInfo['openidList']);
            // 循环发送
            foreach ($openidInfo['openidList'] as $openid){
                $payload = [
                    'appid' => $appid,
                    'refresh_token' => $refresh_token,
                    'openid' => $openid,
                ];
                $serv->task($payload);
            }
            $openid_reids = new Openid();
            $openid_reids->fans_num($appid, 'set', $openidInfo['fanstotal']);
        }
    }

    // 监听异步task事件
    public function on_task($serv, $task_id, $src_worker_id, $data)
    {
        $appid = $data['appid'];
        $refresh_token = $data['refresh_token'];
        $openid = $data['openid'];

        try {
            $res = $this->get_fans_info($appid, $refresh_token, $openid);
            $info = json_decode($res,true);
            if (array_key_exists('nickname', $info)) {
                $payload = array(
                    'nickname' => $info['nickname'],
                    'sex' => $info['sex'],
                    "city" => $info['city'],
                );
                $openid_reids = new Openid();
                $openid_reids->save_fans_info($appid, json_encode($payload));
            }
        }catch (HttpException $exception) {
            Log::error($exception);
        } catch (Exception $exception) {
            Log::error($exception);
        }
    }

    // 监听服务关闭事件
    public function on_close($server, $fd, $reactorId)
    {
        echo "客户端关闭\n";
    }

    public function get_all_openid($token)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='.$token;
        $list = $this->http_get($url);
        if(!$list){
            return $this->api_resp_error('请求失败');
        }
        $data = json_decode($list,true);
        if (!array_key_exists('next_openid', $data)) {
            return;
        }
        $nextOpenid = $data['next_openid'];
        $openidList = $data['data']['openid'];
        if($data['total'] > 10000){
            $num = ceil($data['total']/10000);
            for ($i = 0;$i<$num-1;$i++){
                $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='.$token.'&next_openid='.$nextOpenid;
                $list = $this->http_get($url);
                $data = json_decode($list,true);
                $nextOpenid = $data['next_openid'];
                if ($data['data']['openid']) {
                    $openidList = array_merge($openidList,$data['data']['openid']);
                }
            }
        }
        $dataList['fanstotal'] = $data['total'];
        $dataList['openidList'] = $openidList;
        return $dataList;
    }

    /**
     * 获取公众号单个粉丝详细信息
     *
     * 因为swoole服务器长时间连接
     * 所以进行无mysql数据操作
     * 又因为swoole task大量异步操作
     * 所以不使用easywechat的获取粉丝数据方法
     *
     * @param $appid 公众号appid
     * @param $refresh_token 公众号刷新令牌
     * @param $openid 粉丝openid
     * @return bool|mixed 粉丝详细信息
     */
    public function get_fans_info($appid, $refresh_token, $openid)
    {
        $token = Cache::get('access_token' . $appid);
        if (!$token) {
            $token = $this->platform->get_gh_token_no_db($appid, $refresh_token);
        }
        $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$token.'&openid='.$openid.'&lang=zh_CN';
        $res = $this->http_get($url);
        return $res;
    }

    // curl GET请求
    public function http_get($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($curl);
        if (curl_errno($curl))
        {
            return false;
        }
        curl_close($curl);
        return $data;
    }

}

$server = new Infoserver();